﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Http;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using PNProject.Controllers;
using PNProject.EF;

namespace PNProject
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public class Config
        {
            //public const string RoutingExtension = ".aspx";
            public const string RoutingExtension = "";
        }
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}" + Config.RoutingExtension + "/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );
            routes.MapRoute(
                "Default1", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected void Application_Start()
        {
            IoC.Initialize();
            AreaRegistration.RegisterAllAreas();
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            GlobalConfig.CustomizeConfig(System.Web.Http.GlobalConfiguration.Configuration);
            GlobalConfiguration.Configuration.Formatters.Insert(0, new TextMediaTypeFormatter());
            GlobalConfiguration.Configuration.Formatters.Insert(1, new FileTypeFormatter());
            //ConfigureApi(GlobalConfiguration.Configuration);
            //Bootstrapper.Initialise();
            // Register global filter
            GlobalFilters.Filters.Add(new UserTrackingActionFilterAttribute());
            
        }

        protected void Session_Start()
        {
            var visit = StaticData.settingRepo.GetOne(a => a.SKey == "visit");
            if (visit == null)
            {
                long time = PNLibraries.PNConvertToTimestamp(DateTime.Now);
                Setting set = new Setting();
                set.SKey = "visit";
                set.SValue = "1*1*1*" + time.ToString();
                StaticData.settingRepo.Save(null, set);
            }
            else
            {
                Setting newvisit = new Setting();
                newvisit.SettingID = visit.SettingID;
                newvisit.SKey = "visit";
                var split = visit.SValue.Split('*');
                int today = int.Parse(split[0]);
                int month = int.Parse(split[1]);
                int total = int.Parse(split[2]);
                long last = long.Parse(split[3]);
                var lasttime = PNLibraries.PNTimeStampToDateTime(last);
                DateTime cdate = DateTime.Now;
                long timestamp = PNLibraries.PNConvertToTimestamp(cdate);
                if (cdate.Day == lasttime.Day)
                {
                    today++;
                    month++;
                    total++;

                }
                else
                {
                    if (cdate.Month != lasttime.Month)
                    {
                        today = 1;
                        month = 1;
                        total = total + 1;
                    }
                    else
                    {
                        today = 1;
                        month++;
                        total = total + 1;
                    }
                }
                newvisit.SValue = today.ToString() + "*" + month.ToString() + "*" + total.ToString() + "*" + timestamp.ToString();
                StaticData.settingRepo.Save(visit, newvisit);
            }
        }
        void ConfigureApi(HttpConfiguration config)
        {
            //var unity = new UnityContainer();
            //unity.RegisterType<AccountController>();
            //unity.RegisterType<ICatalogServices, CatalogServices>(
            //    new HierarchicalLifetimeManager());
            //config.DependencyResolver = new IoCContainer(unity);
        }

    }

    /// <summary>
    /// Provides properties and methods for defining a localized route, and for getting information about the localized route.
    /// </summary>
    public class LocalizedRoute : Route
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern and handler class.
        /// </summary>
        /// <param name="url">The URL pattern for the route.</param>
        /// <param name="routeHandler">The object that processes requests for the route.</param>
        public LocalizedRoute(string url, IRouteHandler routeHandler)
            : base(url, routeHandler)
        {
        }

        /// <summary>
        /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class and default parameter values.
        /// </summary>
        /// <param name="url">The URL pattern for the route.</param>
        /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
        /// <param name="routeHandler">The object that processes requests for the route.</param>
        public LocalizedRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
            : base(url, defaults, routeHandler)
        {
        }

        /// <summary>
        /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values and constraints.
        /// </summary>
        /// <param name="url">The URL pattern for the route.</param>
        /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
        /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
        /// <param name="routeHandler">The object that processes requests for the route.</param>
        public LocalizedRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler routeHandler)
            : base(url, defaults, constraints, routeHandler)
        {
        }

        /// <summary>
        /// Initializes a new instance of the System.Web.Routing.Route class, using the specified URL pattern, handler class, default parameter values,
        /// constraints,and custom values.
        /// </summary>
        /// <param name="url">The URL pattern for the route.</param>
        /// <param name="defaults">The values to use if the URL does not contain all the parameters.</param>
        /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
        /// <param name="dataTokens">Custom values that are passed to the route handler, but which are not used to determine whether the route matches a specific URL pattern. The route handler might need these values to process the request.</param>
        /// <param name="routeHandler">The object that processes requests for the route.</param>
        public LocalizedRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            : base(url, defaults, constraints, dataTokens, routeHandler)
        {
        }

        #endregion Constructors

        /// <summary>
        /// Returns information about the requested route.
        /// </summary>
        /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
        /// <returns>
        /// An object that contains the values from the route definition.
        /// </returns>
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
            //string old = virtualPath;
            string cultureCode = "vi-VN";
            if (virtualPath.IsLocalizedUrl())
            {
                cultureCode = virtualPath.Substring(2, 5);
            }
            CultureInfo culture = null;
            try
            {
                culture = CultureInfo.GetCultureInfo(cultureCode);
            }
            catch { }
            if (culture != null)
            {
                System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
            }
            //In ASP.NET Development Server, an URL like "http://localhost/Blog.aspx/Categories/BabyFrog" will return
            //"~/Blog.aspx/Categories/BabyFrog" as AppRelativeCurrentExecutionFilePath.
            //However, in II6, the AppRelativeCurrentExecutionFilePath is "~/Blog.aspx"
            //It seems that IIS6 think we're process Blog.aspx page.
            //So, I'll use RawUrl to re-cereate an AppRelativeCurrentExecutionFilePath like ASP.NET Development Server.
            virtualPath = "~" + httpContext.Request.RawUrl;

            virtualPath = cultureCode == "vi-VN" ? virtualPath : string.Concat("~/", (virtualPath.Length <= 8 ? string.Empty : virtualPath.Substring(8)));
            httpContext.RewritePath(virtualPath, true);

            RouteData data = base.GetRouteData(httpContext);
            //httpContext.Response.Write(data.Values["controller"].ToString() + "-" + data.Values["action"].ToString() + "-" + data.Values["id"].ToString() + "-" + old + "-" + httpContext.Request.RawUrl);
            //httpContext.Response.End();
            return data;
        }

        /// <summary>
        /// Returns information about the URL that is associated with the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains information about the URL that is associated with the route.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            VirtualPathData data = base.GetVirtualPath(requestContext, values);

            if (data != null)
            {
                string rawUrl = requestContext.HttpContext.Request.RawUrl;
                if (rawUrl.IsLocalizedUrl(true))
                {
                    data.VirtualPath = string.Concat(rawUrl.GetLocalizedCultureCode(), "/", data.VirtualPath);
                }
            }
            return data;
        }
    }

    public static class RegexRouteCollectionExtensions
    {
        //Override for localized route
        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults)
        {
            return routes.MapRoute(name, url, defaults, null, null);
        }

        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints)
        {
            return routes.MapRoute(name, url, defaults, constraints, null);
        }

        public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
        {
            //if(url[2]=='-' && url[5]=='/')  //first 5 character is
            if (routes == null)
            {
                throw new ArgumentNullException("routes");
            }
            if (url == null)
            {
                throw new ArgumentNullException("url");
            }
            LocalizedRoute item = new LocalizedRoute(url, new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(defaults),
                Constraints = new RouteValueDictionary(constraints),
                DataTokens = new RouteValueDictionary()
            };
            if ((namespaces != null) && (namespaces.Length > 0))
            {
                item.DataTokens["Namespaces"] = namespaces;
            }
            routes.Add(name, item);
            return item;
            //return routes.MapRoute(name, urlPattern, defaults, null);
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints, string[] namespaces)
        {
            if ((namespaces == null) && (context.Namespaces != null))
            {
                namespaces = context.Namespaces.ToArray();
            }

            Route route = context.Routes.MapRoute(name, url, defaults, constraints, namespaces);
            route.DataTokens["area"] = context.AreaName;
            bool flag = (namespaces == null) || (namespaces.Length == 0);
            route.DataTokens["UseNamespaceFallback"] = flag;
            return route;
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url, object defaults, string[] namespaces)
        {
            return context.MapLocalizedRoute(name, url, defaults, null, namespaces);
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints)
        {
            return context.MapLocalizedRoute(name, url, defaults, constraints, null);
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url, string[] namespaces)
        {
            return context.MapLocalizedRoute(name, url, null, namespaces);
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url, object defaults)
        {
            return context.MapLocalizedRoute(name, url, defaults, null);
        }

        public static Route MapLocalizedRoute(this AreaRegistrationContext context, string name, string url)
        {
            return context.MapLocalizedRoute(name, url, null);
        }
    }

    public class UserTrackingActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext context)
        {
            base.OnResultExecuting(context);
            var controller = context.Controller;
            //save url, userId from session, etc...
        }
    }
}